/**
  ******************************************************************************
  * @file    dht11.c
  * @author  ashuai0110
  * @version V2.4
  * @date    2024-09-10
  * @brief   DHT11温湿度模块驱动
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module.git
  *
  * Change Logs:
  * Date          Author        Notes
  * 2024-03-30    ashuai0110    完成基本内容
  * 2024-07-24    ashuai0110    修改使用组件提供的延时函数
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "dht11.h"

/**
 * @addtogroup devices
 * @{
 */

/**
 * @defgroup dht11 dht11
 * @{
 */

/* 私有宏定义-----------------------------------------------------------------*/

/* 私有类型定义---------------------------------------------------------------*/

/* 私有变量-------------------------------------------------------------------*/

/* 全局变量-------------------------------------------------------------------*/

/* 私有函数原型---------------------------------------------------------------*/
/**
 * @defgroup dht11_local_functions dht11 local functions
 * @{
 */

/**
  * @brief  dht11复位信号
  *
  * @param  _dht11 : dht11管理实例
  *
  * @retval None
  */
static __inline void dht11_reset(dht11_t *_dht11)
{
    _dht11->ioModeSetFn(DHT11_MODE_OUTPUT);
    _dht11->ioReadWriteFn(DHT11_MODE_WRITE, 0);
    mw_delay_ms(20);
    _dht11->ioReadWriteFn(DHT11_MODE_WRITE, 1);
    mw_delay_us(30);
}

/**
  * @brief  dht11响应信号
  *
  * @param  _dht11 : dht11管理实例
  *
  * @retval None
  */
static __inline uint8_t dht11_respond(dht11_t *_dht11)
{
    uint8_t timeoutCnt = 0;
    
    _dht11->ioModeSetFn(DHT11_MODE_INPUT);
    
    while(0 != _dht11->ioReadWriteFn(DHT11_MODE_READ, 0))
    {
        if(timeoutCnt++ < 100)
        {
            mw_delay_us(1);
        }
        else
        {
            return MW_RET_ERR;
        }
    }
    timeoutCnt = 0;
    while(0 == _dht11->ioReadWriteFn(DHT11_MODE_READ, 0))
    {
        if(timeoutCnt++ < 100)
        {
            mw_delay_us(1);
        }
        else
        {
            return MW_RET_ERR;
        }
    }
    
    return MW_RET_OK;
}

/**
  * @brief  dht11读1bit
  *
  * @param  _dht11 : dht11管理实例
  *
  * @retval 返回0或1
  */
static __inline uint8_t dht11_read_bit(dht11_t *_dht11)
{
    uint8_t timeoutCnt = 0;
    
    while(0 != _dht11->ioReadWriteFn(DHT11_MODE_READ, 0))
    {
        if(timeoutCnt++ < 40)
        {
            mw_delay_us(1);
        }
        else
        {
            break;
        }
    }
    timeoutCnt = 0;
    while(0 == _dht11->ioReadWriteFn(DHT11_MODE_READ, 0))
    {
        if(timeoutCnt++ < 40)
        {
            mw_delay_us(1);
        }
        else
        {
            break;
        }
    }
    mw_delay_us(40);
    
    return _dht11->ioReadWriteFn(DHT11_MODE_READ, 0);
}

/**
  * @brief  dht11读1byte
  *
  * @param  _dht11 : dht11管理实例
  *
  * @retval 返回1byte数据
  */
static uint8_t dht11_read_byte(dht11_t *_dht11)
{
    uint8_t cnt = 8, byte = 0;
    
    while(cnt--)
    {
        byte <<= 1;
        byte |= dht11_read_bit(_dht11);
    }
    
    return byte;
}

/**
 * @}
 */

/**
 * @defgroup dht11_global_functions dht11 global functions
 * @{
 */

/**
  * @brief  dht11初始化
  *
  * @param  _dht11      : dht11管理实例
  *
  * @param  ioModeSetFn : IO端口模式设置函数
  *
  * @param  ioRWFn      : IO端口读写函数
  *
  * @retval None
  */
void dht11_init(dht11_t *_dht11, dht11_io_mode_set_fn_t ioModeSetFn, dht11_io_rw_fn_t ioRWFn)
{
    MW_ASSERT_PARAM(IS_VALID_POINTER(_dht11));
    MW_ASSERT_PARAM(IS_VALID_POINTER(ioModeSetFn));
    MW_ASSERT_PARAM(IS_VALID_POINTER(ioRWFn));
    
    /* 初始化各参数 */
    memset(_dht11, 0, sizeof(dht11_t));
    _dht11->ioModeSetFn = ioModeSetFn;
    _dht11->ioReadWriteFn = ioRWFn;
}

/**
  * @brief  dht11读取温湿度数据
  *
  * @param  _dht11     : dht11管理实例
  *
  * @retval 返回读取结果
  *    @arg MW_RET_OK  : 读取成功
  *    @arg MW_RET_ERR : 读取失败
  */
uint8_t dht11_read_data(dht11_t *_dht11)
{
    uint8_t ret;

    dht11_reset(_dht11);
    ret = dht11_respond(_dht11);
    if(MW_RET_OK == ret)
    {
        _dht11->humiInte = dht11_read_byte(_dht11);
        _dht11->humiDeci = dht11_read_byte(_dht11);
        _dht11->tempInte = dht11_read_byte(_dht11);
        _dht11->tempDeci = dht11_read_byte(_dht11);
        ret = dht11_read_byte(_dht11);
        if(ret == _dht11->humiInte + _dht11->humiDeci + _dht11->tempInte + _dht11->tempDeci)
        {
            ret = MW_RET_OK;
        }
        else
        {
            ret = MW_RET_ERR;
        }
    }
    
    return ret;
}

/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */
